//12．创建一个文本文件，内含20行，每行30个整数。这些整数都在0～9之间，用空格分开。
//该文件是用数字表示一张图片，0～9表示逐渐增加的灰度。
//编写一个程序，把文件中的内容读入一个20×30的int数组中。
//一种把这些数字转换为图片的粗略方法是：
//  该程序使用数组中的值初始化一个20×31的字符数组，
//  用值0对应空格字符，1对应点字符，以此类推。数字越大表示字符所占的空间越大。(0-9对应" .':~*=&%@")
//  例如，用#表示9。每行的最后一个字符（第31个）是空字符，这样该数组包含了20个字符串。
//  最后，程序显示最终的图片（即，打印所有的字符串），并将结果储存在文本文件中。
//  例如，下面是开始的数据：
//13．用变长数组（VLA）代替标准数组，完成编程练习12。
//14．数字图像，尤其是从宇宙飞船发回的数字图像，可能会包含一些失真。
//为编程练习12添加消除失真的函数。该函数把每个值与它上下左右相邻的值作比较，
//如果该值与其周围相邻值的差都大于1，则用所有相邻值的平均值（四舍五入为整数）代替该值。
//注意，与边界上的点相邻的点少于4个，所以做特殊处理。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <math.h>

#define ROW 20
#define COLUM 30
#define LEVELS 10
const char trans[LEVELS + 1] = " .':~*=&%#";

static void set_data(int row, int column, char data[row][column], FILE *file);

static void show_data(int row, int column, char data[row][column]);

//p12.13.14
int main(int size, char **argv) {
    char data[ROW][COLUM + 1];
    FILE *file;
    char *filename;
    if (size < 2) {
        puts("Usage p12 filename");
        exit(EXIT_FAILURE);
    }
    filename = argv[1];
    if ((file = fopen(filename, "r")) == NULL) {
        fprintf(stderr, "Could not open data file.\n");
        exit(EXIT_FAILURE);
    }
    set_data(ROW, COLUM + 1, data, file);
    show_data(ROW, COLUM + 1, data);
    return 0;
}

static void set_data(int row, int column, char data[row][column], FILE *file) {
    int data_t[row][column-1];
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column - 1; ++j) {
            fscanf(file, "%1d",&data_t[i][j]);
        }
    }

    //p14
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column - 1; ++j) {
            int left_column = j - 1;
            int right_column = j + 1;
            int up_row = i - 1;
            int down_row = i + 1;
            bool avg1 = left_column > -1 && up_row > -1 && abs(data_t[i][j] - data_t[up_row][left_column]) > 1;
            bool avg2 = left_column > -1 && down_row <row && abs(data_t[i][j] -data_t[down_row][left_column]) > 1;
            bool avg3 = right_column < column-1 && up_row > -1 && abs(data_t[i][j] - data_t[up_row][right_column]) > 1;
            bool avg4 = right_column < column-1 && down_row < row && abs(data_t[i][j] - data_t[down_row][right_column]) > 1;
            if (avg1 && avg2 && avg3 && avg4) {
                data_t[i][j] = (data_t[up_row][left_column] + data_t[down_row][left_column] + data_t[up_row][right_column] +
                        data_t[down_row][right_column]) / 4;
            }
        }
        for (int i = 0; i < row; ++i) {
            for (int j = 0; j < column - 1; ++j) {
                data[i][j] = trans[data_t[i][j]];
            }
            data[i][column - 1] = '\0';
        }
    }
}

static void show_data(int row, int column, char data[row][column]) {
    for (int i = 0; i < row; ++i) {
        puts(data[i]);
    }
}